home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gas / src138.zoo / expr.c < prev    next >
C/C++ Source or Header  |  1991-02-05  |  30KB  |  977 lines

  1. /* expr.c -operands, expressions-
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * This is really a branch office of as-read.c. I split it out to clearly
  22.  * distinguish the world of expressions from the world of statements.
  23.  * (It also gives smaller files to re-compile.)
  24.  * Here, "operand"s are of expressions, not instructions.
  25.  */
  26.  
  27. #include <ctype.h>
  28. #include "as.h"
  29. #include "flonum.h"
  30. #include "read.h"
  31. #include "struc-symbol.h"
  32. #include "expr.h"
  33. #include "obstack.h"
  34. #include "symbols.h"
  35.  
  36. static void clean_up_expression();    /* Internal. */
  37. extern const char EXP_CHARS[];    /* JF hide MD floating pt stuff all the same place */
  38. extern const char FLT_CHARS[];
  39.  
  40. #ifdef SUN_ASM_SYNTAX
  41. extern int local_label_defined[];
  42. #endif
  43.  
  44. /*
  45.  * Build any floating-point literal here.
  46.  * Also build any bignum literal here.
  47.  */
  48.  
  49. /* LITTLENUM_TYPE    generic_buffer [6];    /* JF this is a hack */
  50. /* Seems atof_machine can backscan through generic_bignum and hit whatever
  51.    happens to be loaded before it in memory.  And its way too complicated
  52.    for me to fix right.  Thus a hack.  JF:  Just make generic_bignum bigger,
  53.    and never write into the early words, thus they'll always be zero.
  54.    I hate Dean's floating-point code.  Bleh.
  55.  */
  56. LITTLENUM_TYPE    generic_bignum [SIZE_OF_LARGE_NUMBER+6];
  57. FLONUM_TYPE    generic_floating_point_number =
  58. {
  59.   & generic_bignum [6],        /* low (JF: Was 0) */
  60.   & generic_bignum [SIZE_OF_LARGE_NUMBER+6 - 1], /* high JF: (added +6) */
  61.   0,                /* leader */
  62.   0,                /* exponent */
  63.   0                /* sign */
  64. };
  65. /* If nonzero, we've been asked to assemble nan, +inf or -inf */
  66. int generic_floating_point_magic;
  67.  
  68. /*
  69.  * Summary of operand().
  70.  *
  71.  * in:    Input_line_pointer points to 1st char of operand, which may
  72.  *    be a space.
  73.  *
  74.  * out:    A expressionS. X_seg determines how to understand the rest of the
  75.  *    expressionS.
  76.  *    The operand may have been empty: in this case X_seg == SEG_NONE.
  77.  *    Input_line_pointer -> (next non-blank) char after operand.
  78.  *
  79.  */
  80.  
  81. static segT
  82. operand (expressionP)
  83.      register expressionS *    expressionP;
  84. {
  85.   register char        c;
  86.   register char *name;    /* points to name of symbol */
  87.   register struct symbol *    symbolP; /* Points to symbol */
  88.  
  89.   extern  char hex_value[];    /* In hex_value.c */
  90.   char    *local_label_name();
  91.  
  92.   SKIP_WHITESPACE();        /* Leading whitespace is part of operand. */
  93.   c = * input_line_pointer ++;    /* Input_line_pointer -> past char in c. */
  94.   if (isdigit(c))
  95.     {
  96.       register valueT    number;    /* offset or (absolute) value */
  97.       register short int digit;    /* value of next digit in current radix */
  98.                 /* invented for humans only, hope */
  99.                 /* optimising compiler flushes it! */
  100.       register short int radix;    /* 8, 10 or 16 */
  101.                 /* 0 means we saw start of a floating- */
  102.                 /* point constant. */
  103.       register short int maxdig;/* Highest permitted digit value. */
  104.       register int    too_many_digits; /* If we see >= this number of */
  105.                 /* digits, assume it is a bignum. */
  106.       register char *    digit_2; /* -> 2nd digit of number. */
  107.                int    small;    /* TRUE if fits in 32 bits. */
  108.  
  109.       if (c=='0')
  110.     {            /* non-decimal radix */
  111.       if ((c = * input_line_pointer ++)=='x' || c=='X')
  112.         {
  113.           c = * input_line_pointer ++; /* read past "0x" or "0X" */
  114.           maxdig = radix = 16;
  115.           too_many_digits = 9;
  116.         }
  117.       else
  118.         {
  119.           /* If it says '0f' and the line ends or it DOESN'T look like
  120.              a floating point #, its a local label ref.  DTRT */
  121.           if(c=='f' && (! *input_line_pointer ||
  122.                 (!index("+-.0123456789",*input_line_pointer) &&
  123.                  !index(EXP_CHARS,*input_line_pointer))))
  124.         {
  125.               maxdig = radix = 10;
  126.           too_many_digits = 11;
  127.           c='0';
  128.           input_line_pointer-=2;
  129.         }
  130.           else if (c && index (FLT_CHARS,c))
  131.         {
  132.           radix = 0;    /* Start of floating-point constant. */
  133.                 /* input_line_pointer -> 1st char of number. */
  134.           expressionP -> X_add_number =  - (isupper(c) ? tolower(c) : c);
  135.         }
  136.           else
  137.         {        /* By elimination, assume octal radix. */
  138.           radix = 8;
  139.           maxdig = 10;    /* Un*x sux. Compatibility. */
  140.           too_many_digits = 11;
  141.         }
  142.         }
  143.       /* c == char after "0" or "0x" or "0X" or "0e" etc.*/
  144.     }
  145.       else
  146.     {
  147.       maxdig = radix = 10;
  148.       too_many_digits = 11;
  149.     }
  150.       if (radix)
  151.     {            /* Fixed-point integer constant. */
  152.                 /* May be bignum, or may fit in 32 bits. */
  153. /*
  154.  * Most numbers fit into 32 bits, and we want this case to be fast.
  155.  * So we pretend it will fit into 32 bits. If, after making up a 32
  156.  * bit number, we realise that we have scanned more digits than
  157.  * comfortably fit into 32 bits, we re-scan the digits coding
  158.  * them into a bignum. For decimal and octal numbers we are conservative: some
  159.  * numbers may be assumed bignums when in fact they do fit into 32 bits.
  160.  * Numbers of any radix can have excess leading zeros: we strive
  161.  * to recognise this and cast them back into 32 bits.
  162.  * We must check that the bignum really is more than 32
  163.  * bits, and change it back to a 32-bit number if it fits.
  164.  * The number we are looking for is expected to be positive, but
  165.  * if it fits into 32 bits as an unsigned number, we let it be a 32-bit
  166.  * number. The cavalier approach is for speed in ordinary cases.
  167.  */
  168.       digit_2 = input_line_pointer;
  169.       for (number=0;  (digit=hex_value[c])<maxdig;  c = * input_line_pointer ++)
  170.         {
  171.           number = number * radix + digit;
  172.         }
  173.       /* C contains character after number. */
  174.       /* Input_line_pointer -> char after C. */
  175.       small = input_line_pointer - digit_2 < too_many_digits;
  176.       if ( ! small)
  177.         {
  178.           /*
  179.            * We saw a lot of digits. Manufacture a bignum the hard way.
  180.            */
  181.           LITTLENUM_TYPE *    leader;    /* -> high order littlenum of the bignum. */
  182.           LITTLENUM_TYPE *    pointer; /* -> littlenum we are frobbing now. */
  183.           long int        carry;
  184.  
  185.           leader = generic_bignum;
  186.           generic_bignum [0] = 0;
  187.           generic_bignum [1] = 0;
  188.                 /* We could just use digit_2, but lets be mnemonic. */
  189.           input_line_pointer = -- digit_2; /* -> 1st digit. */
  190.           c = *input_line_pointer ++;
  191.           for (;   (carry = hex_value [c]) < maxdig;   c = * input_line_pointer ++)
  192.         {
  193.           for (pointer = generic_bignum;
  194.                pointer <= leader;
  195.                pointer ++)
  196.             {
  197.               long int    work;
  198.  
  199.               work = carry + radix * * pointer;
  200.               * pointer = work & LITTLENUM_MASK;
  201.               carry = work >> LITTLENUM_NUMBER_OF_BITS;
  202.             }
  203.           if (carry)
  204.             {
  205.               if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)
  206.             {    /* Room to grow a longer bignum. */
  207.               * ++ leader = carry;
  208.             }
  209.             }
  210.         }
  211.           /* Again, C is char after number, */
  212.           /* input_line_pointer -> after C. */
  213.           know( BITS_PER_INT == 32 );
  214.           know( LITTLENUM_NUMBER_OF_BITS == 16 );
  215.           /* Hence the constant "2" in the next line. */
  216.           if (leader < generic_bignum + 2)
  217.         {        /* Will fit into 32 bits. */
  218.           number =
  219.             ( (generic_bignum [1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS )
  220.             | (generic_bignum [0] & LITTLENUM_MASK);
  221.           small = TRUE;
  222.         }
  223.           else
  224.         {
  225.           number = leader - generic_bignum + 1;    /* Number of littlenums in the bignum. */
  226.         }
  227.         }
  228.       if (small)
  229.         {
  230.           /*
  231.            * Here with number, in correct radix. c is the next char.
  232.            * Note that unlike Un*x, we allow "011f" "0x9f" to
  233.            * both mean the same as the (conventional) "9f". This is simply easier
  234.            * than checking for strict canonical form. Syntax sux!
  235.            */
  236.           if (number<10)
  237.         {
  238. #ifdef SUN_ASM_SYNTAX
  239.           if (c=='b' || (c=='$' && local_label_def